#!@pathperl@
# -*- perl -*-

# Copyright (c) 2002-2005 Intel Corporation
# All rights reserved.
#
# This file is distributed under the terms in the attached INTEL-LICENSE
# file. If you do not find these files, copies can be found by writing to
# Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
# 94704.  Attention:  Intel License Inquiry.

# The new nesdoc implementation. When run with a TinyOS 1.x setup, just runs
# the old nesdoc except if the -new option is given.
#
# The new nesdoc implementation is based on the XML dump facilities in nesC
# 1.2 (version 1.2.1 of the nesC compiler is required). Documentation
# generation is broken into two phases:
# - nesdoc data collection: nesdoc information for all interfaces and
#   components is saved to a nesdoc repository, which is just a collection
#   of XML files. See archive.py for more details.
# - HTML generation from the XML files: once a repository is complete,
#   you run nesdoc with the -html option to generate HTML files for
#   each interface and component, along with an index. See genhtml.py
#   for details.
#
# Differences between the old and new nesdocs (summary):
# - the new nesdoc is currently only targeted at generating API documentation;
#   it doesn't generate HTML files describing applications
# - the old nesdoc does not support generic components or interfaces
# - the per-component HTML files, the index and wiring graphs are hopefully
#   more readable
# - information on module implementations is not included (it should not
#   be part of an API documentation)


$prefix = "@prefix@";
$exec_prefix = "@exec_prefix@";
$libprogs = "@libdir@/tinyos";
$python = "@pathpython@";

# nesdoc for TinyOS 2.x
# parse arguments

for ($i = 0; $i <= $#ARGV; $i++) {
	$strip = 0;
	$_ = $ARGV[$i];
	if (/^-/) {
		if (/^-topdir=(.*)/) {
			push @archive_args, "--topdir=$1";
			$strip = 1;
		}
		elsif (/^-tosdir=(.*)/) {
			$tosdir = $1;
			$strip = 1;
		}
		elsif (/^--version$/) {
			$print_version = 1;
			$strip = 1;
		}
		elsif (/^-v$/) {
			$verbose = 1;
		}
		elsif (/^-target=(.*)/) {
			$target = $1;
		}
		elsif (/^-o/) {
			($i, $docdir) = extractarg($i);
			$strip = 1;
		}
		elsif (/^-html$/) {
			$genhtml = 1;
			$strip = 1;
		}
		elsif (/^-preserve$/) {
			$preserve = 1;
			$strip = 1;
		}
		elsif (/^-app$/) {
			$app = 1;
			$strip = 1;
		}
		elsif (/^-quiet$/) {
			$quiet = 1;
			$strip = 1;
		}
	}
	push @ncc_args, $_ if !$strip;
}

if ($print_version) {
	print "nesdoc: @PACKAGE_VERSION@\n";
	exit 0;
}

fail("No documentation directory specified") if !defined $docdir;
fail("No TinyOS tos directory specified") if !defined $tosdir;

$docdir = "$docdir/$target";

if (defined $ENV{PYTHONPATH}) {
	$ENV{PYTHONPATH} = "$libprogs:$PYTHONPATH";
}
else {
	$ENV{PYTHONPATH} = "$libprogs";
}

if ($genhtml) {
	push @html_args, $python;
	push @html_args, "$libprogs/nesdoc/genhtml.py";
	push @html_args, "--quiet" if $quiet;
	push @html_args, $docdir;
	execorfail(@html_args);
}

# Collecting nesdoc data. Run ncc, then process the results with
# nesdoc-archive

unshift @ncc_args, "-tosdir=$tosdir";
unshift @ncc_args, "-fsyntax-only";
unshift @ncc_args, "-fnesc-dump=wiring" if $app;
unshift @ncc_args, "-fnesc-dump=interfacedefs";
unshift @ncc_args, "-fnesc-dump=components(wiring)";
unshift @ncc_args, "-fnesc-dump=interfaces";
unshift @ncc_args, "-fnesc-dump=functions(!global())";
unshift @ncc_args, "-fnesc-dump=referenced(interfaces,components,functions)";
unshift @ncc_args, "$exec_prefix/bin/ncc";

print STDERR join(' ', @ncc_args), "\n" if $verbose;

pipe FORARCHIVE, FORNCC;

if (!($pid = fork())) {
	close STDOUT;
	open STDOUT, ">&FORNCC";
	execorfail(@ncc_args);
}
fail("fork failed") if $pid < 0;
close STDIN;
open STDIN, "<&FORARCHIVE";
# Top of TinyOS tree is a default "topdir" (for package emulation)
$toscontainer = `dirname $tosdir`;
chomp $toscontainer;
push @archive_args, "--topdir=$toscontainer";
push @archive_args, "--preserve" if $preserve;
push @archive_args, "--app" if $app;
push @archive_args, "--quiet" if $quiet;
push @archive_args, "$docdir";
unshift @archive_args, "$libprogs/nesdoc/archive.py";
unshift @archive_args, $python;

print STDERR join(' ', @archive_args), "\n" if $verbose;

fail("Couldn't create directory $docdir") if system("mkdir -p \"$docdir\"");
execorfail(@archive_args);

sub fail {
	print STDERR "$_[0]\n";
	exit 2;
}

sub execorfail {
	exec @_;
	fail("Couldn't execute $_[0]");
}

sub usage {
	fail(<<EOM
Usage: nesdoc -o <documentation directory> <ncc options and nesC files>
	 Compile specified files and archive the resulting nesdoc
	 information in <documentation directory>
	 Note: This does not generate the nesdoc html pages.

	   nesdoc -o <documentation directory> -html
	 Generate nesdoc html pages from archived nesdoc information.

	   nesdoc -o <documentation directory> -app <ncc options and nesC file>
	 Compile specified nesC application and generate a wiring graph
	 for the whole program in the current directory.
EOM
)
}

sub extractarg {
	local ($i) = @_;

	if (length($ARGV[$i]) == 2) {
		$arg = $ARGV[++$i];
	}
	else {
		$arg = substr($ARGV[$i], 2);
	}
	return ($i, $arg);
}
